#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent) {
    workspace = new QWorkspace(this);
    setCentralWidget(workspace);
    connect(workspace, SIGNAL(windowActivated(QWidget*)), this, SLOT(slotUpdateMenus()));
    windowMapper = new QSignalMapper(this);
    connect(windowMapper, SIGNAL(mapped(QWidget*)), workspace, SLOT(setActiveWindow(QWidget*)));

    readSettings();

    createActions();
    createMenus();
    createToolBar();
    createStatusBar();
    createDockWindows();

    setWindowTitle("Flavor");
}

void MainWindow::createActions() {
    openAction = new QAction(QIcon(":/open.svg"), tr("&Open..."), this);
    openAction->setShortcuts(QKeySequence::Open);
    openAction->setStatusTip(tr("Open saved spectrum"));
    openAction->setToolTip(tr("Open saved spectrum"));
    connect(openAction, SIGNAL(triggered()), this, SLOT(slotOpen()));

    saveAction = new QAction(QIcon(":/save.svg"), tr("&Save"), this);
    saveAction->setShortcuts(QKeySequence::Save);
    saveAction->setStatusTip(tr("Save spectrum"));
    saveAction->setToolTip(tr("Save spectrum"));
    connect(saveAction, SIGNAL(triggered()), this, SLOT(slotSaveAs()));

    exitAction = new QAction(QIcon(":/exit.svg"), tr("E&xit"), this);
    exitAction->setShortcut(tr("Ctrl+Q"));
    exitAction->setStatusTip(tr("Exit"));
    exitAction->setToolTip(tr("Exit"));
    connect(exitAction, SIGNAL(triggered()), this, SLOT(close()));

    pdfAction = new QAction(QIcon(":/pdf.svg"), tr("Export"), this);
    pdfAction->setShortcut(tr("Ctrl+P"));
    pdfAction->setStatusTip(tr("Export to PDF"));
    pdfAction->setToolTip(tr("Export to PDF"));
    connect(pdfAction, SIGNAL(triggered()), this, SLOT(slotToPdf()));

    copyAction = new QAction(QIcon(":/copy.svg"), tr("&Copy"), this);
    copyAction->setShortcuts(QKeySequence::Copy);
    copyAction->setStatusTip(tr("Copy spectrum to clipboard"));
    copyAction->setToolTip(tr("Copy spectrum to clipboard"));
    connect(copyAction, SIGNAL(triggered()), this, SLOT(slotCopy()));

    distractAction = new QAction(QIcon(":/distract.svg"), tr("&Distract"), this);
    distractAction->setShortcuts(QKeySequence::Paste);
    distractAction->setStatusTip(tr("Distract spectrum stored in clipboard from current"));
    distractAction->setToolTip(tr("Distract spectrum stored in clipboard from current"));
    connect(distractAction, SIGNAL(triggered()), this, SLOT(slotDistract()));

    colorAction = new QAction(tr("&Set Spectra Background Color"), this);
    connect(colorAction, SIGNAL(triggered()), this, SLOT(slotChangeColor()));

    aboutAction = new QAction(tr("&About"), this);
    aboutAction->setStatusTip(tr("Show About box"));
    connect(aboutAction, SIGNAL(triggered()), this, SLOT(slotAbout()));

    closeAction = new QAction(tr("Cl&ose"), this);
    closeAction->setShortcut(tr("Ctrl+F4"));
    closeAction->setStatusTip(tr("Close the active window"));
    connect(closeAction, SIGNAL(triggered()), workspace, SLOT(closeActiveWindow()));

    closeAllAction = new QAction(tr("Close &All"), this);
    closeAllAction->setStatusTip(tr("Close all the windows"));
    connect(closeAllAction, SIGNAL(triggered()), workspace, SLOT(closeAllWindows()));

    tileAction = new QAction(tr("&Tile"), this);
    tileAction->setStatusTip(tr("Tile the windows"));
    connect(tileAction, SIGNAL(triggered()), workspace, SLOT(tile()));

    cascadeAction = new QAction(tr("&Cascade"), this);
    cascadeAction->setStatusTip(tr("Cascade the windows"));
    connect(cascadeAction, SIGNAL(triggered()), workspace, SLOT(cascade()));

    arrangeAction = new QAction(tr("Arrange &icons"), this);
    arrangeAction->setStatusTip(tr("Arrange the icons"));
    connect(arrangeAction, SIGNAL(triggered()), workspace, SLOT(arrangeIcons()));

    nextAction = new QAction(tr("Ne&xt"), this);
    nextAction->setStatusTip(tr("Move the focus to the next window"));
    connect(nextAction, SIGNAL(triggered()), workspace, SLOT(activateNextWindow()));

    previousAction = new QAction(tr("Pre&vious"), this);
    previousAction->setStatusTip(tr("Move the focus to the previous window"));
    connect(previousAction, SIGNAL(triggered()), workspace, SLOT(activatePreviousWindow()));

    separatorAction = new QAction(this);
    separatorAction->setSeparator(true);
}

void MainWindow::createMenus() {
    fileMenu = menuBar()->addMenu(tr("&File"));
    fileMenu->addAction(openAction);
    fileMenu->addAction(saveAction);
    fileMenu->addSeparator();
    fileMenu->addAction(pdfAction);
    fileMenu->addSeparator();
    fileMenu->addAction(exitAction);

    editMenu = menuBar()->addMenu(tr("&Edit"));
    editMenu->addAction(copyAction);
    editMenu->addAction(distractAction);

    optionsMenu = menuBar()->addMenu(tr("&Options"));
    optionsMenu->addAction(colorAction);

    windowMenu = menuBar()->addMenu(tr("&Window"));
    slotUpdateWindowMenu();
    connect(windowMenu, SIGNAL(aboutToShow()), this, SLOT(slotUpdateWindowMenu()));

    menuBar()->addSeparator();

    helpMenu = menuBar()->addMenu(tr("&Help"));
    helpMenu->addAction(aboutAction);

    slotUpdateMenus();
}

void MainWindow::createToolBar() {
    toolBar = new QToolBar(tr("ToolBar"));
    toolBar->addAction(openAction);
    toolBar->addAction(saveAction);
    toolBar->addAction(copyAction);
    toolBar->addAction(distractAction);
    toolBar->addAction(pdfAction);
    toolBar->addAction(exitAction);
    toolBar->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea);
    addToolBar(Qt::TopToolBarArea, toolBar);
}

void MainWindow::createStatusBar() {
    statusBar()->showMessage(tr("Ok"), 2000);
}

void MainWindow::createDockWindows() {
    model = new CommonOptionsTableModel();

    parameterDockWidget = new ParameterDockWidget(this, model);
    parameterDockWidget->setWindowTitle(tr("Spectrum parameters"));
    parameterDockWidget->setFeatures(QDockWidget::DockWidgetMovable);
    parameterDockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
    addDockWidget(Qt::LeftDockWidgetArea, parameterDockWidget);

    connect(workspace, SIGNAL(windowActivated(QWidget*)), this, SLOT(slotUpdate(QWidget*)));
}

void MainWindow::closeEvent(QCloseEvent* event) {
    workspace->closeAllWindows();
    if (activeSpectrumView()) {
        event->ignore();
    } else {
        writeSettings();
        event->accept();
    }
}

void MainWindow::slotToPdf() const {
    activeSpectrumView()->toPdf();
}

void MainWindow::slotOpen() {
    QString fileName = QFileDialog::getOpenFileName(this, tr("Open Precise Spectrum"), "", tr("Precise spectrum files (*.psf)"));
    if (fileName.isEmpty()) {
        return;
    }
    SpectrumView* existing = findSpectrumView(fileName);
    if (existing) {
        workspace->setActiveWindow(existing);
        return;
    }

    SpectrumView* child = createSpectrumView();
    if (child->loadFile(fileName)) {
        statusBar()->showMessage(tr("File loaded"), 2000);
        child->showMaximized();
    } else {
        child->close();
    }
}

void MainWindow::slotSaveAs() const {
    if (activeSpectrumView()->saveAs()) {
        statusBar()->showMessage(tr("Spectrum saved"), 2000);
    }
}

void MainWindow::slotCopy() const {
    activeSpectrumView()->copy();
}

void MainWindow::slotAbout() {
    QMessageBox::about(this, tr("About"), tr("Flavor port to Qt."));
}

void MainWindow::slotUpdate(QWidget* w) {
    SpectrumView* sw = qobject_cast<SpectrumView*>(w);
    model->newData(sw == NULL? QSharedPointer<CommonOptions>(): sw->commonOptions());
}

void MainWindow::slotDistract() {
    activeSpectrumView()->distract();
}

void MainWindow::slotChangeColor() {
    QColorDialog* cDialog = new QColorDialog(this);
    connect(cDialog, SIGNAL(colorSelected(const QColor &)), this, SLOT(slotSetBackgroundColor(const QColor&)));
    cDialog->open();
}

void MainWindow::slotSetBackgroundColor(const QColor& color) {
    QList<QWidget*> windows = workspace->windowList();
    for (int i = 0; i < windows.size(); ++i) {
        SpectrumView* child = qobject_cast<SpectrumView*>(windows.at(i));
        if (child == NULL) {
            continue;
        }

        child->setBackgroundColor(color);
    }
    settings->setValue("color", color);
    writeSettings();
}

void MainWindow::slotUpdateMenus() {
    bool hasSpectrumView = (activeSpectrumView() != NULL);
    copyAction->setEnabled(hasSpectrumView);
    saveAction->setEnabled(hasSpectrumView);
    pdfAction->setEnabled(hasSpectrumView);
    distractAction->setEnabled(hasSpectrumView && !QApplication::clipboard()->text().isEmpty());//!!!!!
    closeAction->setEnabled(hasSpectrumView);
    closeAllAction->setEnabled(hasSpectrumView);
    tileAction->setEnabled(hasSpectrumView);
    cascadeAction->setEnabled(hasSpectrumView);
    arrangeAction->setEnabled(hasSpectrumView);
    nextAction->setEnabled(hasSpectrumView);
    previousAction->setEnabled(hasSpectrumView);
    separatorAction->setVisible(hasSpectrumView);
}

void MainWindow::slotUpdateWindowMenu() {
    windowMenu->clear();
    windowMenu->addAction(closeAction);
    windowMenu->addAction(closeAllAction);
    windowMenu->addSeparator();
    windowMenu->addAction(tileAction);
    windowMenu->addAction(cascadeAction);
    windowMenu->addAction(arrangeAction);
    windowMenu->addSeparator();
    windowMenu->addAction(nextAction);
    windowMenu->addAction(previousAction);
    windowMenu->addAction(separatorAction);

    QList<QWidget*> windows = workspace->windowList();
    separatorAction->setVisible(!windows.isEmpty());

    for (int i = 0; i < windows.size(); ++i) {
        SpectrumView* child = qobject_cast<SpectrumView*>(windows.at(i));
        if (child == NULL) {
            continue;
        }

        QString text;
        if (i < 9) {
            text = tr("&%1 %2").arg(i + 1).arg(child->userFriendlyCurrentFile());
        } else {
            text = tr("%1 %2").arg(i + 1).arg(child->userFriendlyCurrentFile());
        }
        QAction* action = windowMenu->addAction(text);
        action->setCheckable(true);
        action->setChecked(child == activeSpectrumView());
        connect(action, SIGNAL(triggered()), windowMapper, SLOT(map()));
        windowMapper->setMapping(action, child);
    }
}

SpectrumView* MainWindow::createSpectrumView() {
    QColor color = settings->value("color", Qt::white).value<QColor>();
    SpectrumView* child = new SpectrumView(color, this);
    workspace->addWindow(child);

    connect(child, SIGNAL(copyAvailable(bool)), distractAction, SLOT(setEnabled(bool)));

    return child;
}

SpectrumView* MainWindow::activeSpectrumView() const {
    return qobject_cast<SpectrumView*>(workspace->activeWindow());
}

SpectrumView* MainWindow::findSpectrumView(const QString& fileName) const {
    QString canonicalFilePath = QFileInfo(fileName).canonicalFilePath();

    foreach (QWidget* window, workspace->windowList()) {
        SpectrumView* spectrumView = qobject_cast<SpectrumView*>(window);
        if (spectrumView->currentFile() == canonicalFilePath) {
            return spectrumView;
        }
    }
    return NULL;
}

void MainWindow::readSettings() {
    settings = new QSettings("Mass-Spec Lab", "Flavor(Qt)", this);
    if (!settings->contains("color")) {
        settings->setValue("color", Qt::white);
        settings->sync();
    }
}

void MainWindow::writeSettings() {
    settings->sync();
}
